Smart pointer

스마트 포인터(Smart Pointer)
스마트 포인터를 이용해서 프로그래머의 실수로 메모리 누수(Memory Leak)이 발생하는 것을 방어 할 수 있는
수단이다. 포인터처럼 동작하는 클래스 템플릿(Class Template)이다.

기본적으로 힙 영역에 동적 할당되어 메모리를 해제하기 위해서는 delete 키워드를 사용하면 된다.
스마트 포인터를 사용시 메모리 누수를 효과적으로 방지할 수 있기 때문에 컴퓨터 시스템의 안정성을 높일 수 있다.

Java, C#. Python의 가비지 콜렉터와 유사한 기능을 한다.
일반적으로 new 키워드를 이용해서 기본 포인터가 특정한 메모리 주소를 가리키도록 초기화한 이후,
스마트 포인터에 해당 포인터를 넣어서 사용할 수 있다.

정의된 스마트 포인터가 수명을 다했을 때, 소멸자에서 delete 키워드를 이용해, 할당된 메모리들을 자동으로 해제하는 기능을 수행한다.
스마트 포인터 객체
unique_ptr;        하나의 스마트 포인터가 특정한 객체를 처리할 수 있도록 한다.
shared_ptr;        특정한 객체를 참조하는 스마트 포인터가 총 몇개인지를 참조한다.
weak_ptr;            하나 이상의 shared_ptr 인스턴스가 소유하는 객체에 대한 접근을 제공한다.(부가적 역할)
unique_ptr
C++에서 하나의 스마트 포인터만이 특정한 객체를 처리하도록 할 때, 사용할 수 있다.
스마트 포인터가 특정한 객체의 소유권을 가지고 있을 때만, 소멸자가 객체를 삭제할 수 있다.
move()        // 포인터 소유권 이전
reset()        // 메모리 할당 해제
#include <iostream>
using namespace std;
int main(void){
unique_ptr<int> p1(new int(10));
unique_ptr<int> p2;
cout<<" 1: "<<p1<<'\n';
cout<<" 2: "<<p2<<'\n';
cout<<"----- -----\n";
p2=move(p1);
cout<<" 1: "<<p1<<'\n';
cout<<" 2: "<<p2<<'\n';
cout<<"----- ------";
p2.reset();
cout<<" 1: "<<p1<<'\n';
cout<<" 2: "<<p2<<'\n';
system("pause");
return 0;
}

스마트 포인터 1: 0x100542760

스마트 포인터 2: 0x0

----- 소유권 이전 -----

스마트 포인터 1: 0x0

스마트 포인터 2: 0x100542760

----- 메모리 할당 해제 ------

스마트 포인터 1: 0x0

스마트 포인터 2: 0x0

unieque_ptr을 이용한 객체에 접근
포인터로 객체에 접근시 포인터처럼 객체의 데이터를 반환
#include <iostream>
using namespace std;
int main(void){
unique_ptr<int> p1(new int(10));
cout<<*p1<<'\n';
system("pause");
}

10

#include <iostream>
using namespace std;
int main(void){
int* arr=new int[10];
unique_ptr<int> p1(arr); // unique_ptr
for(int i=0;i<10;i++){
arr[i]=i;
}
for(int i=0;i<10;i++){
cout<<arr[i]<<' ';
}
p1.reset();
cout<<'\n';
for(int i=0;i<10;i++){ //
cout<<arr[i]<<' ';
}
system("pause");
}
shared_ptr
하나의 특정한 객체를 참조하는 스마트 포인터의 개수가 몇 개인지 참조한다.

특정한 객체를 새로운 스마트 포인터가 참조할 때마자 참조 횟수(Reference Count)가 1씩 증가하며,
각 스마트 포인터의 수명이 다할 때마다 1씩 감소한다.
참조 횟수가 0이되면 delete 키워드를 이용해서 메모리에서 데이터를 자동으로 할당 해제한다.

use_count()        //참조하고 있는 객체의 갯수를 반환
#include <iostream>
using namespace std;
int main(void){
int* arr=new int[10];
arr[7]=100;
shared_ptr<int> p1(arr);
cout<<p1.use_count()<<'\n'; // 1
shared_ptr<int> p2(p1);
cout<<p1.use_count()<<'\n'; // 2
shared_ptr<int> p3=p2;
cout<<p1.use_count()<<'\n'; // 3
p1.reset();
p2.reset();
cout<<"arr[7]: "<<arr[7]<<'\n'; // 1, 2 3
p3.reset();
cout<<p1.use_count()<<'\n';
cout<<"arr[7]: "<<arr[7]<<'\n'; //
system("pause");
return 0;
}
weak_ptr
하나 이상의 shared_ptr 객체가 참조하고 있는 객체에 접근할 수 있다.
하지만 해당 객체의 소유자의 수에는 포함되지 않는 스마트 포인터이다.

일반적으로 서로 상대방을 가르키는 두 개의 shared_ptr가 있다면, 참조 횟수는 0이 될수 없다.
따라서 메모리에서 해제될 수 없다. weak_ptr은 위와 같은 순환 참조(Circular Referance)현상을
제거하기 위한 목적으로 사용할 수 있다.

use_count()        // waek_ptr이 포인팅하고 있는 객체 수
lock()        // 자신이 가리키고 있는 포인터 반환
#include <iostream>
using namespace std;
int main(void){
int* arr=new int(1);
shared_ptr<int> sp1(arr);
weak_ptr<int> wp=sp1;
cout<<sp1.use_count()<<'\n';
cout<<wp.use_count()<<'\n';
if(true){
shared_ptr<int> sp2=wp.lock();
cout<<sp1.use_count()<<'\n';
cout<<wp.use_count()<<'\n';
} // (if)
cout<<sp1.use_count()<<'\n';
cout<<wp.use_count()<<'\n';
system("pause");
return 0;
}

1

1

2

2

1

1